<script setup>
import {ElLoading, ElMessage} from "element-plus"
import {ref} from 'vue'
import {PhotoCompress} from "@/utils/compressUtil.js";

defineProps({
  visible: Boolean
})
const emits = defineEmits(['update:visible', 'uploadImage'])

const imageUrl = ref('')
const linkUrl = ref('')

const handleClose = () => {
  emits("update:visible", false)
  imageUrl.value = ''
  linkUrl.value = ''
}

/**
 * @param {File} rawFile
 * @returns {Promise<boolean>}
 */
const handleBeforeUpload = async (rawFile) => {

  if (!(rawFile.type + '').startsWith('image/')) {
    ElMessage.error('不支持的文件格式')
    return false
  }
  // 需要压缩图片
  const minSize = 10 * 1024 // 最小10k
  const maxSize = 500 * 1024 // 最大500k
  if (rawFile.size > maxSize) {
    const photoCompress = new PhotoCompress(minSize, maxSize)
    photoCompress.compress(rawFile,  async (file) => {
      const url = await fileToBase64(file)
      imageUrl.value = `data:${rawFile.type};base64,${url}`
    })
  } else {
    const url = await fileToBase64(rawFile)
    imageUrl.value = `data:${rawFile.type};base64,${url}`
  }

  return false
}

/**
 *
 * @param {File} file
 * @returns {Promise}
 */
const fileToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    // 创建一个新的 FileReader 对象
    const reader = new FileReader()
    // 读取 File 对象
    reader.readAsDataURL(file)
    // 加载完成后
    reader.onload = function () {
      // 将读取的数据转换为 base64 编码的字符串
      const base64String = reader.result.split(",")[1]
      // 解析为 Promise 对象，并返回 base64 编码的字符串
      resolve(base64String)
    }

    // 加载失败时
    reader.onerror = function () {
      reject(new Error("Failed to load file"))
    }
  })
}

const confirmImage = async () => {
  if (imageUrl.value === '' && linkUrl.value === '') {
    ElMessage.warning('请上传图片或输入图片地址')
    return
  }
  if (imageUrl.value) {
    emits('uploadImage', imageUrl.value)
    handleClose()
  } else {
    const load = ElLoading.service({fullscreen: true, text: '图片加载中...'})
    const imgRes = await checkImageExists(linkUrl.value).then(() => true).catch(() => false)
    load.close()
    if (imgRes) {
      emits('uploadImage', linkUrl.value)
      handleClose()
    } else {
      ElMessage.warning('不是一个有效的图片链接')
    }
  }
}

const checkImageExists = (url) => {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.src = url
    img.onload = (res) => {
      resolve(res)
    }
    img.onerror = (err) => {
      reject(err)
    }
  })
}
</script>

<template>
  <el-dialog
      :model-value="visible"
      center
      title="图片"
      width="500px"
      @close="handleClose"
  >
    <h4 class="padding-bottom-5">方式一：本地上传图片</h4>
    <el-upload
        drag
        action="#"
        accept="image/*"
        :show-file-list="false"
        :before-upload="handleBeforeUpload"
        class="mind-map-drag"
    >
      <div v-if="!imageUrl" style="padding: 40px 0">
        <el-icon class="el-icon--upload">
          <component is="UploadFilled"/>
        </el-icon>
        <div class="el-upload__text">
          拖拽图片到此处或 <em>点击上传</em>
        </div>
      </div>
      <div v-else style="position: relative">
        <el-icon class="del-icon" @click.stop="imageUrl = ''">
          <component is="delete"/>
        </el-icon>
        <el-image :src="imageUrl" style="height: 187px"/>
      </div>
    </el-upload>
    <h4 class="padding-top-20 padding-bottom-5">方式二：网络图片</h4>
    <el-input v-model="linkUrl" placeholder="输入网络图片连接，以http://或https://开头" clearable/>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">取消</el-button>
        <el-button type="primary" @click="confirmImage"> 确定</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<style scoped lang="scss">
.del-icon {
  color: var(--el-color-danger);
  font-size: 20px;
  position: absolute;
  right: 0;
  top: 0;
  z-index: 1;
  background: rgba(0, 0, 0, 0.2);
}
</style>
<style lang="scss">
.mind-map-drag .el-upload-dragger {
  padding: 0 20px;
}
</style>